
#ifndef GAME_H
#define GAME_H

#include <System/Object.h>
#include <System/String.h>
#include <System/Exception.h>
#include <System/IDisposable.h>
#include <System/EventArgs.h>
#include <System/TimeSpan.h>

#include <CSharpPropertyMethods.h>

#include "Graphics/GraphicsDevice.h"
#include "GameWindow.h"

#include <Riccsson/Xna/Framework/Content/ContentManager.h>

#if Windows_

#include <Windows.h>

// For Windows.
extern int LoadGLTextures(const char* imageFilename, unsigned int& generatedTexture_out, int& width_out , int& height_out);

#endif

#if Windows

#include <Windows.h>
#include <gl/GLee.h>

extern void ReSizeGLScene(int width, int height);

extern HWND g_hWnd;

#else

//#include <jni.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
//#include <GLES/gl.h>
//#include <pthread.h>
//#include <EGL/egl.h> // requires ndk r5 or newer
//#include <android/native_window.h>

//#include <GLES/gl.h>

class EGLClass;
class ANativeWindow;

#endif

// For Android.

extern bool setupGraphics(int w, int h);

//#endif


namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			class GameComponentCollection{ public: GameComponentCollection(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			//class GraphicsDevice{ public: GraphicsDevice(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			//class TimeSpan{ public: TimeSpan(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			class LaunchParameters{ public: LaunchParameters(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			class GameServiceContainer{ public: GameServiceContainer(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			//class GameWindow{ public: GameWindow(){ throw Riccsson::System::Exception("Class not implemented yet."); } };
			class GameTime;
			//class EventArgs;

			class Game :
				public Riccsson::System::Object,
				public Riccsson::System::IDisposable
			{

				
				bool _initialize();
				
				public: static volatile bool initializedComplete;

#if Windows
				public: static volatile bool renderingEnabled;
#else
			private:
				static Game* _oneInstance;
				EGLClass* m_eglClass;
				void _setWindow(ANativeWindow* window);

			public:
				static void setWindow(ANativeWindow* window)
				{
					_oneInstance->_setWindow(window);
				}
#endif

			private: GC_PTR<Content::ContentManager> _Content;

					// Summary:
					//     Gets the collection of GameComponents owned by the game.
			public: PROP3(Game, GC_PTR<GameComponentCollection>, Components)
					// Summary:
					//     Gets or sets the current ContentManager.
			public: PROP3_DEF(Game, GC_PTR<Content::ContentManager>, Content)
					//
					// Summary:
					//     Gets the current GraphicsDevice.
			public: PROP3(Game, GC_PTR<Graphics::GraphicsDevice>, graphicsDevice)
					//
					// Summary:
					//     Gets or sets the time to sleep when the game is inactive.
			public: PROP3(Game, Riccsson::System::TimeSpan, InactiveSleepTime)
					//
					// Summary:
					//     Indicates whether the game is currently the active application.
			public: PROP3(Game, bool, IsActive)
					//
					// Summary:
					//     Gets or sets a value indicating whether to use fixed time steps.
			public: PROP3(Game, bool, IsFixedTimeStep)
					//
					// Summary:
					//     Gets or sets a value indicating whether the mouse cursor should be visible.
			public: PROP3(Game, bool, IsMouseVisible)
					//
					// Summary:
					//     Gets the start up parameters in LaunchParameters.
			public: PROP3(Game, GC_PTR<LaunchParameters>, launchParameters)
					//
					// Summary:
					//     Gets the GameServiceContainer holding all the service providers attached
					//     to the Game.
			public: PROP3(Game, GC_PTR<GameServiceContainer>, Services)
					//
					// Summary:
					//     Gets or sets the target time between calls to Update when IsFixedTimeStep
					//     is true. Reference page contains links to related code samples.
			public: PROP3(Game, Riccsson::System::TimeSpan, TargetElapsedTime)
					//
					// Summary:
					//     Gets the underlying operating system window.
			public: PROP3(Game, GC_PTR<GameWindow>, Window)

					
			COPY_CONSTRUCTOR(Game)
			{
				PROP3_INIT_COPY(Game, GC_PTR<GameComponentCollection>, Components);
				PROP3_INIT_COPY(Game, GC_PTR<Content::ContentManager>, Content);
				PROP3_INIT_COPY(Game, GC_PTR<Graphics::GraphicsDevice>, graphicsDevice);
				PROP3_INIT_COPY(Game, Riccsson::System::TimeSpan, InactiveSleepTime);
				PROP3_INIT_COPY(Game, bool, IsActive);
				PROP3_INIT_COPY(Game, bool, IsFixedTimeStep);
				PROP3_INIT_COPY(Game, bool, IsMouseVisible);
				PROP3_INIT_COPY(Game, GC_PTR<LaunchParameters>, launchParameters);
				PROP3_INIT_COPY(Game, GC_PTR<GameServiceContainer>, Services);
				PROP3_INIT_COPY(Game, Riccsson::System::TimeSpan, TargetElapsedTime);
				PROP3_INIT_COPY(Game, GC_PTR<GameWindow>, Window);
			}

			public: Game();
			public: ~Game(void);

					// Summary:
					//     Gets the collection of GameComponents owned by the game.
			public: PROP3_GET(GC_PTR<GameComponentCollection>, Components){ return _PROP_Components; } //GameComponentCollection Components { get; }
			private: PROP3_SET(GC_PTR<GameComponentCollection>, Components){ }
					 //
					 // Summary:
					 //     Gets or sets the current ContentManager.
			public: PROP3_GET(GC_PTR<Content::ContentManager>, Content){ return _Content; } //ContentManager Content { get; set; }
			public: PROP3_SET(GC_PTR<Content::ContentManager>, Content){ _Content = value; }
					//
					// Summary:
					//     Gets the current GraphicsDevice.
			public: PROP3_GET(GC_PTR<Graphics::GraphicsDevice>, graphicsDevice){ return _PROP_graphicsDevice; }
			private: PROP3_SET(GC_PTR<Graphics::GraphicsDevice>, graphicsDevice){ _PROP_graphicsDevice = value; }
					 //
					 // Summary:
					 //     Gets or sets the time to sleep when the game is inactive.
			public: PROP3_GET(Riccsson::System::TimeSpan, InactiveSleepTime){ return _PROP_InactiveSleepTime; } //TimeSpan InactiveSleepTime { get; set; }
			public: PROP3_SET(Riccsson::System::TimeSpan, InactiveSleepTime){ _PROP_InactiveSleepTime = InactiveSleepTime; }
					//
					// Summary:
					//     Indicates whether the game is currently the active application.
			public: PROP3_GET(bool,IsActive){ return _PROP_IsActive; } //bool IsActive { get; }
			private: PROP3_SET(bool,IsActive){}
					//
					// Summary:
					//     Gets or sets a value indicating whether to use fixed time steps.
			public: PROP3_GET(bool,IsFixedTimeStep){ return _PROP_IsFixedTimeStep; } //bool IsFixedTimeStep { get; set; }
			public: PROP3_SET(bool,IsFixedTimeStep){ _PROP_IsFixedTimeStep = IsFixedTimeStep; }
					//
					// Summary:
					//     Gets or sets a value indicating whether the mouse cursor should be visible.
			public: PROP3_GET(bool,IsMouseVisible){ return _PROP_IsMouseVisible; } //bool IsMouseVisible { get; set; }
			public: PROP3_SET(bool,IsMouseVisible){ _PROP_IsMouseVisible = IsMouseVisible; }
					//
					// Summary:
					//     Gets the start up parameters in LaunchParameters.
			public: PROP3_GET(GC_PTR<LaunchParameters>, launchParameters){ return _PROP_launchParameters; } //LaunchParameters LaunchParameters { get; }
			private: PROP3_SET(GC_PTR<LaunchParameters>, launchParameters){}
					//
					// Summary:
					//     Gets the GameServiceContainer holding all the service providers attached
					//     to the Game.
			public: PROP3_GET(GC_PTR<GameServiceContainer>, Services){ return _PROP_Services; } //GameServiceContainer Services { get; }
			private: PROP3_SET(GC_PTR<GameServiceContainer>, Services){}
					//
					// Summary:
					//     Gets or sets the target time between calls to Update when IsFixedTimeStep
					//     is true. Reference page contains links to related code samples.
			public: PROP3_GET(Riccsson::System::TimeSpan,TargetElapsedTime){ return _PROP_TargetElapsedTime; } //TimeSpan TargetElapsedTime { get; set; }
			public: PROP3_SET(Riccsson::System::TimeSpan,TargetElapsedTime){ _PROP_TargetElapsedTime = TargetElapsedTime; }
					//
					// Summary:
					//     Gets the underlying operating system window.
			public: PROP3_GET(GC_PTR<GameWindow>, Window){ return _PROP_Window; } //GameWindow Window { get; }
			private: PROP3_SET(GC_PTR<GameWindow>, Window){}

					// Summary:
					//     Raised when the game gains focus.
					//
					// Parameters:
					//   :
			public: event<Void, Riccsson::System::Generic::EventHandler<Riccsson::System::EventArgs>> Activated;
					//
					// Summary:
					//     Raised when the game loses focus.
					//
					// Parameters:
					//   :
			public: event<Void, Riccsson::System::Generic::EventHandler<Riccsson::System::EventArgs>> Deactivated;
					//
					// Summary:
					//     Raised when the game is being disposed.
					//
					// Parameters:
					//   :
			public: event<Void, Riccsson::System::Generic::EventHandler<Riccsson::System::EventArgs>> Disposed;
					//
					// Summary:
					//     Raised when the game is exiting.
					//
					// Parameters:
					//   :
			public: event<Void, Riccsson::System::Generic::EventHandler<Riccsson::System::EventArgs>> Exiting;

					// Summary:
					//     Starts the drawing of a frame. This method is followed by calls to Draw and
					//     EndDraw.
			protected: virtual bool BeginDraw();
					   //
					   // Summary:
					   //     Called after all components are initialized but before the first update in
					   //     the game loop.
			protected: virtual void BeginRun();
					   //
					   // Summary:
					   //     Immediately releases the unmanaged resources used by this object.
			public: void Dispose();
					//
					// Summary:
					//     Releases all resources used by the Game class.
					//
					// Parameters:
					//   disposing:
					//     true to release both managed and unmanaged resources; false to release only
					//     unmanaged resources.
			protected: virtual void Dispose(bool disposing);
					   //
					   // Summary:
					   //     Reference page contains code sample.
					   //
					   // Parameters:
					   //   gameTime:
					   //     Time passed since the last call to Draw.
			protected: virtual void Draw(GameTime gameTime);
					   //
					   // Summary:
					   //     Ends the drawing of a frame. This method is preceeded by calls to Draw and
					   //     BeginDraw.
			protected: virtual void EndDraw();
					   //
					   // Summary:
					   //     Called after the game loop has stopped running before exiting.
			protected: virtual void EndRun();
					   //
					   // Summary:
					   //     Exits the game.
			public: void Exit();
					//
					// Summary:
					//     Called after the Game and GraphicsDevice are created, but before LoadContent.
					//     Reference page contains code sample.
			protected: virtual void Initialize();
					   //
			protected: virtual void LoadContent();
					   //
					   // Summary:
					   //     Raises the Activated event. Override this method to add code to handle when
					   //     the game gains focus.
					   //
					   // Parameters:
					   //   sender:
					   //     The Game.
					   //
					   //   args:
					   //     Arguments for the Activated event.
					   //[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
			protected: virtual void OnActivated(Riccsson::System::object* sender, Riccsson::System::EventArgs args);
					   //
					   // Summary:
					   //     Raises the Deactivated event. Override this method to add code to handle
					   //     when the game loses focus.
					   //
					   // Parameters:
					   //   sender:
					   //     The Game.
					   //
					   //   args:
					   //     Arguments for the Deactivated event.
					   //[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
			protected: virtual void OnDeactivated(Riccsson::System::object* sender, Riccsson::System::EventArgs args);
					   //
					   // Summary:
					   //     Raises an Exiting event. Override this method to add code to handle when
					   //     the game is exiting.
					   //
					   // Parameters:
					   //   sender:
					   //     The Game.
					   //
					   //   args:
					   //     Arguments for the Exiting event.
					   //[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
			protected: virtual void OnExiting(Riccsson::System::object* sender, Riccsson::System::EventArgs args);
					   //
					   // Summary:
					   //     Resets the elapsed time counter.
			public: void ResetElapsedTime();
					//
					// Summary:
					//     Call this method to initialize the game, begin running the game loop, and
					//     start processing events for the game.
			public: void Run();
					//
					// Summary:
					//     Run the game through what would happen in a single tick of the game clock;
					//     this method is designed for debugging only.
			public: void RunOneFrame();
					//
					// Summary:
					//     This is used to display an error message if there is no suitable graphics
					//     device or sound card.
					//
					// Parameters:
					//   exception:
					//     The exception to display.
			protected: virtual bool ShowMissingRequirementMessage(const Riccsson::System::Exception& exception);
					   //
					   // Summary:
					   //     Prevents calls to Draw until the next Update.
			public: void SuppressDraw();
					//
					// Summary:
					//     Updates the game's clock and calls Update and Draw.
			public: void Tick();
					//
					// Summary:
					//     Called when graphics resources need to be unloaded. Override this method
					//     to unload any game-specific graphics resources.
			protected: virtual void UnloadContent();
					   //
					   // Summary:
					   //     Reference page contains links to related conceptual articles.
					   //
					   // Parameters:
					   //   gameTime:
					   //     Time passed since the last call to Update.
			protected: virtual void Update(GameTime gameTime);

			};
		}
	}
}

#endif
